import React, { useCallback, useEffect, useState } from 'react';
import { motion } from 'framer-motion';
import { useClickOutside } from 'hooks';
import { observer } from 'mobx-react-lite';

import Input from 'components/Input';
import Text from 'components/Text';
import { TEXT_TAG, TEXT_VIEW } from 'components/Text/Text.types';
import { classnames } from 'utils';

import classes from './SearchInput.module.scss';

export type Option = {
    /** Ключ варианта, используется для отправки на бек/использования в коде */
    key: string;
    /** Значение варианта, отображается пользователю */
    value: string;
};

/** Пропсы, которые принимает компонент Dropdown */
export type SearchInputProps = {
    className?: string;
    inputContainerClassName?: string;
    optionsClassName?: string;
    optionClassName?: string;
    singleValue?: boolean;
    placeholder?: string;
    /** Массив возможных вариантов для выбора */
    options: Option[];
    /** Текущие выбранные значения поля, может быть пустым */
    value: string;
    /** Callback, вызываемый при выборе варианта */
    onChange: (value: string) => void;
    /** Заблокирован ли дропдаун */
    disabled?: boolean;

    onOptionClick: (value: string) => void;
};

const cnSearchInput = classnames(classes, 'searchInput');

const SearchInput: React.FC<SearchInputProps> = ({
    className,
    inputContainerClassName,
    optionsClassName,
    optionClassName,
    options,
    placeholder,
    value,
    onChange,
    disabled,
    onOptionClick,
}) => {
    const [popoverVisible, setPopoverVisible] = useState(false);
    const [dropdownRef, setDropdownRef] = useState<HTMLDivElement | null>(null);

    const handleOnChange = useCallback((value: string) => onChange(value), [onChange]);

    const handleOnClickInput = useCallback(() => {
        if (!disabled) {
            setPopoverVisible(true);
        }
    }, [disabled]);

    const handleOnClickOutside = useCallback(() => {
        setPopoverVisible(false);
    }, []);

    useClickOutside(dropdownRef as HTMLDivElement, handleOnClickOutside);

    const handleOnClickOption = useCallback(
        (newOption: Option) => () => {
            onOptionClick(newOption.value);
            setPopoverVisible(false);
        },
        [],
    );

    useEffect(() => {
        if (disabled) {
            setPopoverVisible(false);
        }
    }, [disabled]);

    return (
        <div className={cnSearchInput() + ` ${className}`} ref={setDropdownRef}>
            <Input
                value={value}
                onChange={handleOnChange}
                disabled={disabled}
                onClick={handleOnClickInput}
                placeholder={placeholder}
                className={inputContainerClassName}
            />
            {popoverVisible && !disabled && (
                <motion.div
                    layout="size"
                    // initial={{ height: 0 }}
                    //animate={{ height: 'auto' }}
                    transition={{ layout: { duration: 0.1 }, ease:"easeIn" }}
                    className={cnSearchInput('options') + ` ${optionsClassName}`}
                >
                    {options.map((option) => (
                        <span key={option.key} onClick={handleOnClickOption(option)}>
                            <Text
                                tag={TEXT_TAG.div}
                                view={TEXT_VIEW.p16}
                                className={cnSearchInput('option') + ` ${optionClassName}`}
                            >
                                {option.value}
                            </Text>
                        </span>
                    ))}
                </motion.div>
            )}
        </div>
    );
};

export default observer(SearchInput);
